#include "StdAfx.h"
#include "LayoutFactory.h"
#include "RelativeLayout.h"

namespace fusion
{
	namespace mode10
	{
		fusion::Ref<LayoutGroup> LayoutFactory::CreateLayout (LayoutType type, const Ref<Node> currentNode)
		{
			Ref<LayoutGroup> base = new RelativeLayout(currentNode.get(), LayoutGroup::GetDefaultParams(currentNode.get()));
			return base;
			//return NULL;
		}
		bool LayoutFactory::AddLayoutEffect(const fusion::Ref<Node>& currentNode, const fusion::Ref<ClientParamsAdapter>& params)
		{
			if (!currentNode->m_parent)
			{
				// cannot do anything...
				return false;
			}
			Node* parent = currentNode->m_parent;

			Ref<LayoutNode> wrap = parent->GetRelatedLayout();
			if (wrap)
			{
				if (wrap->IsLayoutable()) // its a container
				{
					Ref<LayoutGroup> parentLayout = dynamic_cast<LayoutGroup*>(wrap.get());
					//ASSERT(parentLayout);
					// check is the same type
					if (GetLayoutType(wrap) != GetLayoutType(params))
					{
						// show error
						return false;
					}
					return GenerateLayoutParams(parentLayout, currentNode, params);

				} else { // its not a container, transformer it become a layout with its parameter
					// what if anything error here...headache
					Ref<LayoutGroup> parentLayout = CreateLayout(GetLayoutType(params), parent);
					// ASSERT(parentLayout);
					Ref<BaseLayoutParams> parentParams = wrap->GetLayoutParams();
					parentLayout->ReplaceParams(parentParams);
					if (GenerateLayoutParams(parentLayout, currentNode, params))
					{
						// replace wrap as parentLayout
						Ref<LayoutGroup> mostParent = dynamic_cast<LayoutGroup*>(wrap->GetParent().get());
						// ASSERT(mostParent);
						return mostParent->AddLayoutNode(parentLayout) && mostParent->RemoveLayoutNode(wrap);
					}
				}
			} else { // parent don't exist layout yet
				Ref<LayoutGroup> parentLayout = CreateLayout(GetLayoutType(params), parent);
				// ASSERT(parentLayout);
				if (GenerateLayoutParams(parentLayout, currentNode, params))
				{
					//parent->SetRelatedLayout(parentLayout);
					return true;
				}
			}
			return false;
		}

		bool LayoutFactory::RemoveLayoutEffect(Ref<Node>& node)
		{
			Ref<LayoutNode> wrap = node->GetRelatedLayout();
			if (wrap)
			{
				if (wrap->IsLayoutable())
				{
					// add my child to my parent...but if they are not able to fit those parameters...
					Ref<LayoutGroup> parent = dynamic_cast<LayoutGroup*>(wrap->GetParent().get());
					//ASSERT(parent);
					Ref<LayoutGroup> myGroup = dynamic_cast<LayoutGroup*>(wrap.get());
					//ASSERT(myGroup);
					// remove self from parent
					return parent->RemoveLayoutNode(wrap);
				}
			}
			return false;
		}

		bool LayoutFactory::GenerateLayoutParams(const Ref<LayoutGroup>& layout, Ref<Node> currentNode, const Ref<ClientParamsAdapter>& params)
		{
			Ref<BaseLayoutParams> myParams = layout->GenerateLayoutParams(params);
			//ASSERT(myParams);
			Ref<LayoutNode> myNode = new LayoutNode(currentNode.get(), myParams);
			//ASSERT(myNode);
			if (layout->AddLayoutNode(myNode))
			{
				layout->RequestLayout();
				return true;
			}
			return false;
		}
	}
}